#include <iostream>
#include <fstream>
#include <cstdio>
#include <cstring>
#include <string>
#include <vector>
#include <deque>
#include <ranges>
#include <algorithm>
#include <numeric>
#include <omp.h>
//
//定义tick结构体
struct struct_tick
{
double LastPrice, BidPrice1, AskPrice1,OpenInterest;
int Volume, BidVolume1, AskVolume1,hm;
char TradingDay[9], UpdateTime[9];
};


//交易类
class class_trader
{
	public:
double h, l, value, price;
int num,position;
std::vector<std::string> traders;


//初始化
class_trader()
{
h = 0.0;
l = 0.0;
value = 0.0;
price = 0.0;
num = 0;
position = 0;
}


//执行一次
void run(const struct_tick &data, int cc)
{

if(cc > position)
{
value -= (data.AskPrice1 * (cc - position) );
char txt[80] = { 0 };
snprintf(txt, sizeof(txt), "buy,%.2f,%d,%d,%s,%s", data.AskPrice1, cc - position, cc, data.TradingDay, data.UpdateTime);
traders.push_back(txt);
position = cc;
num++;
}
else if(cc < position)
{
value -= (data.BidPrice1 * (cc - position) );
char txt[80] = { 0 };
snprintf(txt, sizeof(txt), "sell,%.2f,%d,%d,%s,%s", data.BidPrice1, cc - position, cc, data.TradingDay, data.UpdateTime);
traders.push_back(txt);
position = cc;
num++;
}

price = value + data.LastPrice * position;
if(price > h)
{
	h = price;
}
else if(price < l) 
{
l = price;
}
}


//写出交易记录
int write_traders(std::string dz)
{
	std::ofstream file(dz.c_str() );
if(!file.is_open() )
{
	std::cout<<"打开文件失败"<<std::endl;
return -1;
}
for(auto &t: traders)
{
file << t << std::endl;
}
file.close();
	return traders.size();
}


	};


//动能策略
std::string drive(std::vector<struct_tick> &ticks, int n, double k)
{
	int length = ticks.size();
	for(int i=length-1; i > 0; --i)
	{
		if(ticks[i].Volume >= ticks[i-1].Volume)
		{
			ticks[i].Volume -= ticks[i-1].Volume;
		}
	}

class class_trader ct;
int cc = 0;
	for(int i = 1; i < length - n; ++i)
	{
		double zz = 0.0;
		double fx = 0.0; 
		for(int j = i; j < i + n; ++j)
		{
			zz += ticks[j].Volume;
			if( (ticks[j].LastPrice > ticks[j-1].LastPrice && ticks[j].OpenInterest > ticks[j-1].OpenInterest) || (ticks[j].LastPrice < ticks[j-1].LastPrice && ticks[j].OpenInterest < ticks[j-1].OpenInterest) )
			{
				fx += ticks[j].Volume;
			}
			else if( (ticks[j].LastPrice < ticks[j-1].LastPrice && ticks[j].OpenInterest > ticks[j-1].OpenInterest) || (ticks[j].LastPrice > ticks[j-1].LastPrice && ticks[j].OpenInterest < ticks[j-1].OpenInterest ) )
			{
				fx -= ticks[j].Volume;
			}
		}
		if(fx / zz > k)
		{
			cc = 1;
		}
		if(fx / zz < - k)
		{
			cc = -1;
		}
		if(cc > 0 && fx / zz < 0)
		{
			cc = 0;
		}
		if(cc < 0 && fx / zz > 0)
		{
			cc = 0;
		}
		zz = 0.0;
		fx = 0.0;
ct.run(ticks[i + n - 1],cc);
	}
char result[200] = { 0 };
snprintf(result, sizeof(result), "%.2f,%.2f,%.2f,%i,%i,%i,%.2f\n", ct.price, ct.h, ct.l, ct.num, ct.position, n, k);
return std::string(result);
}



//弹性网格
std::string grid_5(std::vector<struct_tick> &ticks, double zz)
{
class class_trader ct;
ct.value = zz;
ct.l = zz;
ct.h = zz;
for(auto &tick: ticks)
{
if(tick.AskPrice1 * (ct.position + 2)< ct.value )
{
ct.run(tick, ct.position+1);
std::cout<<"买入"<<ct.position<<","<<tick.AskPrice1<<","<<ct.price<<std::endl;
}
else if(tick.BidPrice1 * (ct.position - 2) > ct.value)
{
ct.run(tick, ct.position -1);
std::cout<<"卖出"<<ct.position<<","<<tick.BidPrice1<<","<<ct.price<<std::endl;
}


}
char result[200] = { 0 };
snprintf(result, sizeof(result), "%.2f,%.2f,%.2f,%i,%i,%.2f\n", ct.price, ct.h, ct.l, ct.num, ct.position, zz);
return std::string(result);
}


//海归策略
std::string turtle(std::vector<struct_tick> &ticks, int n, int k, int p)
{
int ints[10] = {0};
double dous[10] = { 0.0 };
ints[0] = (n * 3 > k ? n * 3 : k );
ints[0] = (ints[0] > p ? ints[0] : p );
ints[0] +=1;

class class_trader bs;
int ccc = 0;
auto datas = std::ranges::subrange(ticks.begin(), ticks.begin() + ints[0] );
dous[1] = std::accumulate(datas.begin() + ints[0] - n * 3, datas.end(), 0.0, [](double x, const struct_tick &y){return x + y.LastPrice;}) / n / 3;
dous[2] = std::accumulate(datas.begin() + ints[0] - n * 2, datas.end(), 0.0, [](double x, const struct_tick &y){return x + y.LastPrice;}) / n / 2;
dous[3] = std::accumulate(datas.begin() + ints[0] - n, datas.end(), 0.0, [](double x, const struct_tick &y){return x + y.LastPrice;}) / n;
struct_tick data={0.0, 0.0, 0.0, 0.0, 0, 0, 0, 0, "", ""};
for(int i=1; i + ints[0] < ticks.size(); ++i)
{
datas = std::ranges::subrange(ticks.begin() + i, ticks.begin() + i + ints[0] );
data= *(datas.begin() + ints[0] - 1);
dous[1] += ( ( (datas.begin() + ints[0] -1)->LastPrice - (datas.begin() + ints[0] - n * 3 - 1)->LastPrice)/ n / 3);
dous[2] += ( ( (datas.begin() + ints[0] - 1)->LastPrice - (datas.begin() + ints[0] - n * 2 - 1)->LastPrice)/ n / 2);
dous[3] += ( ( (datas.begin() + ints[0] -1)->LastPrice - (datas.begin() + ints[0] - n - 1)->LastPrice)/ n);

//交易动作
if(bs.position == 0)
{
{
auto [min_it,max_it] = std::minmax_element(datas.begin() + ints[0] - k, datas.end(), [&](const struct_tick &x, const struct_tick &y){return x.LastPrice < y.LastPrice;}); 
dous[4]=min_it->LastPrice;
dous[5]=max_it->LastPrice;
}
if(data.LastPrice == dous[5] && dous[3] > dous[2] && dous[2] > dous[1] && data.AskPrice1 < 10000000)
{
ccc = 1;
}
else if(data.LastPrice == dous[4] && dous[3] < dous[2] && dous[2] < dous[1] && data.BidPrice1 < 10000000)
{
ccc = -1;
}
}
else if(bs.position == 1) 
{
{
auto [min_it,max_it] = std::minmax_element(datas.begin() + ints[0] - p, datas.end(), [&](const struct_tick &x, const struct_tick &y){return x.LastPrice < y.LastPrice;}); 
dous[6]=min_it->LastPrice;
dous[7]=max_it->LastPrice;
}
if( (data.LastPrice == dous[6] || dous[3] < dous[2] || dous[2] < dous[1]) && data.BidPrice1 < 10000000)
{
	ccc = 0;
}
}
else if(bs.position == -1)
{
{
auto [min_it,max_it] = std::minmax_element(datas.begin() + ints[0] - p, datas.end(), [&](const struct_tick &x, const struct_tick &y){return x.LastPrice < y.LastPrice;}); 
dous[6]=min_it->LastPrice;
dous[7]=max_it->LastPrice;
}
if( (data.LastPrice == dous[7] ||  dous[3] > dous[2] || dous[2] > dous[1]) && data.AskPrice1 < 10000000)
{
ccc = 0;
}
}
bs.run(data, ccc);
}
//输出
char result[200] = { 0 };
snprintf(result, sizeof(result), "%.2f,%.2f,%.2f,%i,%i,%i,%i,%i\n", bs.price, bs.h, bs.l, bs.num, bs.position, n, k, p);
return std::string(result);
}

 int main(int argc, char * argv[])
{
char path[200] = "ticks.dat";
if(argc > 1)
{
	strcpy(path, argv[1]);
}
int num = 1000;
if(argc > 2)
{
	num = atoi(argv[2]);
}
	std::ifstream file(path, std::ios::binary);
std::vector<struct_tick> ticks;
struct_tick tick = {0.0, 0.0, 0.0, 0.0, 0, 0, 0, 0, "", ""};
while(file.read(reinterpret_cast<char *>(&tick), sizeof(tick) ) )
{
ticks.push_back(tick);
}
std::cout<<"读取了"<<ticks.size()<<std::endl;
std::cout<<ticks.begin()->LastPrice<<","<<ticks.rbegin()->LastPrice<<std::endl;
omp_set_num_threads(omp_get_num_procs()); // 设置线程
#pragma omp parallel for schedule(dynamic)
for(int h=600; h <= 36000; h+=600)
{
for(double i=0.01; i<0.2; i += 0.01)
{
	std::cout<<	drive(ticks, h, i);
}
}
//grid_5(ticks, num);
return 0;
struct struct_cs
{
	int n,k,p;
};
std::vector<struct_cs> css;
for(int i = 3600;i <= 36000; i+=3600)
{
for(int j=3600; j <= 36000; j += 1200)
{
for(int k=3600; k <=36000; k +=1200)
{
css.push_back(struct_cs{i,j,k} );
}
}
}
omp_set_num_threads(omp_get_num_procs()); // 设置线程
#pragma omp parallel for schedule(dynamic)
for(auto cs:css)
{
	std::cout<<turtle(ticks, cs.n, cs.k, cs.p);
}
return 0;
}

